﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Shapes;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace DiagramDesigner
{

    public class BasicThumb : Thumb
    {
        private UIElement parent;
        #region Constructor
        public BasicThumb()
        {
            SnapsToDevicePixels = true;
            UseLayoutRounding = false;
            this.DragDelta += new DragDeltaEventHandler(BasicThumb_DragDelta);
        }
        #endregion

        void BasicThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            if (parent == null)
            {
                UIElement element = VisualTreeHelper.GetParent(this) as UIElement;
                while (element != null)
                {
                    // TODO: rework to clean out explicit type specification
                    if (element is ContentPresenter)
                    {                        
                        parent = element;
                        //parent = VisualTreeHelper.GetParent(element) as UIElement;
                        break;
                    }

                    element = VisualTreeHelper.GetParent(element) as UIElement;

                }
            }

            double newX = AnchorPoint.X + e.HorizontalChange / Scale;
            double newY = AnchorPoint.Y + e.VerticalChange / Scale;
            
            if (parent != null)
            {                                                
                newX = Math.Max(0.0, Math.Min(newX, parent.RenderSize.Width));
                newY = Math.Max(0.0, Math.Min(newY, parent.RenderSize.Height));
                //newX = Math.Max(0.0, newX);
                //newY = Math.Max(0.0, newY);
            }

            AnchorPoint = new Point(newX, newY);
        }

        public double LineWidth
        {
            get { return (double)GetValue(LineWidthProperty); }
            set { SetValue(LineWidthProperty, value); }
        }

        // Using a DependencyProperty as the backing store for LineWidth.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LineWidthProperty =
            DependencyProperty.Register("LineWidth", typeof(double), typeof(BasicThumb),
            new FrameworkPropertyMetadata(1.0, FrameworkPropertyMetadataOptions.AffectsMeasure));



        public double Scale
        {
            get { return (double)GetValue(ScaleProperty); }
            set { SetValue(ScaleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Scale.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ScaleProperty =
            DependencyProperty.Register("Scale", typeof(double), typeof(BasicThumb),
            new FrameworkPropertyMetadata(1.0, FrameworkPropertyMetadataOptions.AffectsMeasure));
        

        public Point AnchorPoint
        {
            get { return (Point)GetValue(AnchorPointProperty); }
            set { SetValue(AnchorPointProperty, value); }
        }

        // Using a DependencyProperty as the backing store for AnchorPoint.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AnchorPointProperty =
            DependencyProperty.Register("AnchorPoint", typeof(Point), typeof(BasicThumb),
            new UIPropertyMetadata(new Point(double.NaN, double.NaN), AnchorPointPropertyChangedCallback));        

        private static void AnchorPointPropertyChangedCallback(DependencyObject d,	DependencyPropertyChangedEventArgs e)
        {
            BasicThumb b = d as BasicThumb;
            
            Canvas.SetTop(b, ((Point)e.NewValue).Y);
            Canvas.SetLeft(b, ((Point)e.NewValue).X);

        }


        #region Overrides
        protected override Visual GetVisualChild(int index)
        {
            return null;
        }

        protected override Size MeasureOverride(Size constraint)
        {
            var result = base.MeasureOverride(constraint);
            // ... add custom measure code here if desired ...
            InvalidateVisual();            
            return result;
        }                

        protected override void OnRender(DrawingContext drawingContext)
        {
            //GuidelineSet gs = new GuidelineSet(new double[] { -Width / 2, Width / 2 }, new double[] { -Height / 2, Height / 2 });
            //drawingContext.PushGuidelineSet(gs);
            double lw = LineWidth/Scale;
            double h = Height/Scale;
            double w = Width/Scale;
            drawingContext.DrawRoundedRectangle(Brushes.Transparent, new Pen(Brushes.Black, lw),
                new Rect(-w/2 + 0.5/Scale, -h/2 + 0.5/Scale, w, h), 1.5*lw, 1.5*lw);            
        }
        #endregion

        #region Positioning
        internal void AdjustPos(double dx, double dy)
        {
            Canvas.SetTop(this, Canvas.GetTop(this) + dy);
            Canvas.SetLeft(this, Canvas.GetLeft(this) + dx);
        }

        internal void SetPos(double x, double y)
        {
            Canvas.SetTop(this, y - Height / 2);
            Canvas.SetLeft(this, x - Width / 2);
        }
        #endregion
    }

}